package ru.ifmo.sound;

import ru.ifmo.sound.neuro.LayerBuilder;
import ru.ifmo.sound.neuro.NeuroNet;
import ru.ifmo.sound.neuro.Neuron;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * @author avhaliullin
 */
public class Test2 {
    public static void main(String[] args) {
        final SecureRandom rnd = new SecureRandom();
        double[][] v = new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}};
        NeuroNet neuroNet = new NeuroNet(2, 10, new LayerBuilder() {
            public List<Neuron> build(List<Neuron> prev) {
                List<Neuron> res = new ArrayList<Neuron>();
                res.add(new Neuron());
                res.add(new Neuron());
                res.add(new Neuron());
                res.add(new Neuron());
                for (Neuron neuron : res) {
                    for (Neuron prevNeuron : prev) {
                        neuron.prevLayer.add(neuron.new WeightedNeuron(prevNeuron, rnd.nextDouble() * 10 - 5));
                    }
                }
                return res;
            }
        }, new LayerBuilder() {
            public List<Neuron> build(List<Neuron> prev) {
                List<Neuron> res = new ArrayList<Neuron>();
                res.add(new Neuron());
                for (Neuron neuron : res) {
                    for (Neuron prevNeuron : prev) {
                        neuron.prevLayer.add(neuron.new WeightedNeuron(prevNeuron, rnd.nextDouble() * 10 - 5));
                    }
                }
                return res;
            }
        }
        );
        for (int i = 0; i < 400; i++) {
            boolean result = i % 2 == 1;
            boolean result2 = neuroNet.learn(v[i % 4], result);
            System.out.println(result + " " + result2);
        }
    }

    public static void complexToComplex(int sign, int n,
                                        double ar[], double ai[]) {
        double scale = (double) Math.sqrt(1.0f / n);

        int i, j;
        for (i = j = 0; i < n; ++i) {
            if (j >= i) {
                double tempr = ar[j] * scale;
                double tempi = ai[j] * scale;
                ar[j] = ar[i] * scale;
                ai[j] = ai[i] * scale;
                ar[i] = tempr;
                ai[i] = tempi;
            }
            int m = n / 2;
            while (m >= 1 && j >= m) {
                j -= m;
                m /= 2;
            }
            j += m;
        }

        int mmax, istep;
        for (mmax = 1, istep = 2 * mmax; mmax < n; mmax = istep, istep = 2 * mmax) {
            double delta = (double) sign * 3.141592654f / (double) mmax;
            for (int m = 0; m < mmax; ++m) {
                double w = (double) m * delta;
                double wr = (double) Math.cos(w);
                double wi = (double) Math.sin(w);
                for (i = m; i < n; i += istep) {
                    j = i + mmax;
                    double tr = wr * ar[j] - wi * ai[j];
                    double ti = wr * ai[j] + wi * ar[j];
                    ar[j] = ar[i] - tr;
                    ai[j] = ai[i] - ti;
                    ar[i] += tr;
                    ai[i] += ti;
                }
            }
            mmax = istep;
        }
    }
}
